package com.yorick.login.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yorick.account.entity.AccountDto;
import com.yorick.common.Result.SimpleFactory.ResultFactory;
import com.yorick.common.config.jedis.JedisClient;
import com.yorick.common.error.YorickAssert;
import com.yorick.common.error.YorickException;
import com.yorick.common.util.Encrypt;
import com.yorick.common.util.RSAUtils;
import com.yorick.login.dao.LoginMapper;
import com.yorick.login.modal.request.LoginRequest;
import com.yorick.login.modal.response.LoginResponse;
import com.yorick.login.service.LoginService;
import com.yorick.login.util.Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;

@Slf4j
@Service("loginService")
public class LoginServiceImpl implements LoginService {
    @Resource
    protected LoginMapper loginDao;
    @Resource
    protected ObjectMapper objectMapper;
    @Resource
    protected JedisClient jedisClient;

    @Override
    public Map<String, Object> handleLogin(LoginRequest requestBody, HttpServletRequest request) {
        HttpSession session = request.getSession();//创建session对象

        AccountDto data = AccountDto.builder()
                .account(requestBody.getAccount())
                .password(Encrypt.encrypt(requestBody.getAccount() + requestBody.getPassword()))
                .build();

        AccountDto account = loginDao.getAccount(data);
        validateAccount(data, account);
        //更新登录时间
        loginDao.updateLoginDate(account.getAid());

        Map<String, Object> map = objectMapper.convertValue(account, Map.class);
        Util.saveMapToSession(session, map);

        //封装返回内容
        LoginResponse response = LoginResponse.builder()
                .aid(account.getAid())
                .account(account.getAccount())
                .username(account.getUsername())
                .mobilephone(account.getMobilephone())
                .email(account.getEmail())
                .head(account.getHead())
                .lastTime(account.getLoginDate())
                .fileMaxSize(account.getFileMaxSize())
                .build();


        //单一客户端登录（依靠RSA公钥加密私钥解密机制实现）
        Pair<String, String> keyPair = null;
        try {
            keyPair = RSAUtils.getKeyPair();
            session.setAttribute("token", RSAUtils.encrypt(
                    account.getAccount(),
                    keyPair.getLeft()
            ));
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResultFactory.failure().display();
        }

        jedisClient.set(
                String.format("%s_token", account.getAccount()),
                keyPair.getRight()
        );

        return ResultFactory.success(response).display();
    }

    public void validateAccount(AccountDto data, AccountDto account){
        AccountDto accountStatus = loginDao.getAccountStatus(data);
        Optional<AccountDto> optStatus = Optional.ofNullable(accountStatus);
        optStatus.ifPresent(opt ->{
            YorickAssert.validate(
                    opt.getEnabled()==1,
                    () -> "0",
                    () -> "账户已冻结，请联系管理员"
            );
        });

        Optional<AccountDto> optAccount = Optional.ofNullable(account);
        if (optAccount.isPresent()){
            loginDao.resetFailureTime(data);
        }else{
            loginDao.updateFailureTime(data);
            throw new YorickException("0", "账号密码错误，请检查后重试");
        }
    }
}
